#ifndef MAP_H
#define MAP_H

#include <list>
#include <vector>
#include <map>
#include "singleton.h"
#include <fstream>

class hgeSprite;
class Scene;

struct MapTile
{
    MapTile()
    {
        sprite = NULL;
    }
    int tileid;
    std::string filename;
    hgeSprite *sprite;
};

struct MapElem
{
    int tileid;
    int x;
    int y;
};

struct MapRenderElem
{
    int x;
    int y;
    hgeSprite *sprite;
};

typedef std::vector<MapRenderElem> SortedElemVec;

struct StartPoint
{
    StartPoint()
    {
        mapid=0;
        layer=0;
        x=0;
        y=0;
    }
    int mapid;
    int layer;
    int x;
    int y;
};

enum eRegionCondition
{
   
};

enum eRegionTrigger
{
    RC_Enter = 0,
    RC_Key = 1,
};

enum eRegionAction
{
    RA_Transport = 0,
};

struct RegionTrigger
{
    RegionTrigger()
    {
        triggertype = -1;
        data = -1;
    }
    int triggertype;
    int data;
};

struct RegionCondition
{

};

struct RegionAction
{
    enum
    {
        Transport = 0,
    };
    RegionAction()
    {
        actiontype = -1;
        data = -1;
    }
    void Do( );
    int actiontype;
    int data;
};

struct Region
{
    Region();
    Region(int xx,int yy,int ww,int hh);
    void Save( std::ofstream &f );
    void Load( std::ifstream &f );
    int x;
    int y;
    int w;
    int h;
    int id;
    int mapid;
    int layer;
    RegionTrigger trigger;
    RegionCondition condition;
    RegionAction action;
    std::string name;
};

typedef std::list<MapElem*> MapElemList;
typedef std::map<int,int> TerrainMap;
typedef std::vector<Region *> RegionVec;
class MapLayer
{
public:
    MapLayer();
    ~MapLayer();
    void Render( int x, int y, int layerx, int layery );
    void AddElem( int tileid, int x, int y );
    void Save( std::ofstream &f );
    void Load( std::ifstream &f );
    void RemoveElem( MapElem *elem, bool del = true );
    void GetElemInArea( MapElemList &elemlist, int x1, int y1, int x2, int y2 );
    void SetTerrain( short x, short y, int type );
    int  GetTerrain( short x, short y );
    void RemoveRegion( int id );
    void AddRegion( Region *r );
	void Update( );

    MapElemList mElems;
    TerrainMap mTerrain;
    RegionVec mRegions;
    int mLayerindex;
    MapRenderElem *mPlayerElem;
};

typedef std::vector<MapLayer*> MapLayerVec;

class Map
{
public:
    Map();
    ~Map();
    void Render(int x, int y, int mapx, int mapy);
    MapLayer *GetLayer( int layer );
    void RemoveLayer( int layer );
    void AddLayer( int layer );
    int GetID( ) { return mID; };
    void Save( std::ofstream &f );
    void Load( std::ifstream &f );
	void Update( );

    MapLayerVec mLayers;
    int mID;
    std::string mName;
	Scene *mScene;
};

typedef std::map<int, MapTile *> MapTileMap;
typedef std::map<int, Map*> IDMapMap;
typedef std::map<int, Region *> RegionMap;
class MapManager:public CSingleton<MapManager>
{
    IMPLEMENT_SINGLETON(MapManager);
    friend class CMapLoader;
public:
    Map* CreateMap(int id);
    bool AddMap( Map *map );
    Map* GetMap(int id);
    int GenerateMapID( );
    bool RemoveMap(int id);
    void loadMapTiles( );
    MapTile *GetTile( int id );
    Map * GetMap( std::string name );

    void SetStartPoint( int mapid, int layer, int x, int y );
    void Save( const char *filename );
    void Load( const char *filename );

    int GenerateRegionID( );
    void AddRegion( Region *r );
    void RemoveRegion( int id );
    Region *GetRegion( int id );
    IDMapMap mMaps;
    MapTileMap mTiles;
    StartPoint mStartPoint;
    RegionMap mRegions;
};
#define MapMgr MapManager::Instance()
#endif